<!--
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-07-30 09:14:04
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-08-22 17:57:19
 * @FilePath: /vue3-uniapp/src/components/ui/WyyFilterDropdown/components/DropdownList.vue
-->
<script lang="ts" setup>
interface DropdownListItem {
    value: string | number | boolean | undefined;
    label: string;
}
interface DropdownBtn {
    name: string;
    list: DropdownListItem[];
}

const props = withDefaults(
    defineProps<{
        modelValue: (string | number | boolean | undefined)[];
        dropdownList: DropdownBtn[];
        viewHeight?: string;
        bgColor?: string;
        nameColor?: string;
        nameSize?: string;
        labelColor?: string;
        labelSize?: string;
        activeColor: string;
    }>(),
    {
        modelValue: () => [] as (string | number | boolean | undefined)[],
        viewHeight: '80rpx',
        bgColor: 'var(--bg-front)',
        nameColor: 'var(--c-text)',
        nameSize: 'var(--text-sm)',
        labelColor: 'var(--c-text3)',
        labelSize: 'var(--text-sm)',
        activeColor: 'var(--c-primary)'
    }
);

const emits = defineEmits<{
    (
        event: 'update:model-value',
        value: (string | number | boolean | undefined)[]
    ): void;
    (event: 'clickBtn', index: number): void;
}>();

const {
    dropdownList,
    viewHeight,
    nameColor,
    nameSize,
    modelValue,
    labelColor,
    labelSize,
    activeColor
} = toRefs(props);

const list = ref<DropdownListItem[]>([]);

let top: number | undefined;
const instance = getCurrentInstance();
const handleClickBtn = async (item: DropdownBtn, index: number) => {
    console.log('handleClickBtn', item, index);
    if (top === undefined) {
        top = await new Promise((resolve) => {
            const query = uni.createSelectorQuery().in(instance);
            query
                .select('.dropdownlist-container')
                .boundingClientRect((data) => {
                    const top = Array.isArray(data) ? data[0].top : data.top;
                    if (top === undefined) {
                        throw new Error('[DropdownList]获取不到top');
                    }
                    resolve(top);
                })
                .exec();
        });
    }
    if (showIndex.value !== index) {
        showIndex.value = index;
        list.value = JSON.parse(JSON.stringify(item.list));
        emits('clickBtn', index);
    } else {
        showIndex.value = -1;
        list.value = [];
        emits('clickBtn', -1);
    }
};

const showIndex = ref(-1);
const excuteDropdownIconStyle = (index: number) => {
    if (showIndex.value === index) {
        return {
            transform: 'rotateZ(-180deg)',
            transition: 'transform .3s'
        };
    } else {
        return {
            transform: 'rotateZ(0)',
            transition: 'transform .3s'
        };
    }
};

const handleClickItem = (item: DropdownListItem) => {
    if (showIndex.value !== -1) {
        const arr = [...modelValue.value];
        arr[showIndex.value] = item.value;
        emits('update:model-value', arr);
        list.value = [];
        showIndex.value = -1;
    }
};

defineExpose({
    close: () => {
        showIndex.value = -1;
    }
});
</script>

<template>
    <view
        class="dropdownlist-container"
        :class="{ active: showIndex !== -1 }"
        :style="{ top, background: bgColor }"
    >
        <scroll-view :scroll-x="true" :style="{ height: viewHeight }">
            <view class="btn-list">
                <view
                    v-for="(item, index) in dropdownList"
                    :key="index"
                    class="btn"
                    @click="() => handleClickBtn(item, index)"
                >
                    <text
                        class="mr-[4rpx]"
                        :style="{
                            color:
                                showIndex === index ? activeColor : nameColor,
                            fontSize: nameSize
                        }"
                        >{{ item.name }}</text
                    >
                    <TnIcon
                        name="down-triangle"
                        :custom-style="{
                            color:
                                showIndex === index ? activeColor : nameColor,
                            fontSize: nameSize,
                            ...excuteDropdownIconStyle(index)
                        }"
                    />
                </view>
            </view>
        </scroll-view>
        <view class="list-wrap" v-if="list.length > 0">
            <scroll-view scroll-y class="list">
                <view
                    class="item"
                    v-for="(item, index) in list"
                    :key="index"
                    @click="() => handleClickItem(item)"
                >
                    <view
                        :style="{
                            fontSize: labelSize,
                            color:
                                modelValue[showIndex] &&
                                modelValue[showIndex] === item.value
                                    ? activeColor
                                    : labelColor
                        }"
                        >{{ item.label }}</view
                    >
                    <TnIcon
                        :custom-style="{ color: activeColor }"
                        name="check"
                        v-if="
                            modelValue[showIndex] &&
                            modelValue[showIndex] === item.value
                        "
                    />
                </view>
            </scroll-view>
        </view>
    </view>
</template>

<style lang="scss" scoped>
.dropdownlist-container {
    width: 100%;
    &.active {
        position: fixed;
        left: 0;
        z-index: 11;
    }
    .btn-list {
        height: 100%;
        display: flex;
        flex-direction: row;
        align-items: center;
        flex-wrap: nowrap;
        padding: 0 24rpx;
        .btn {
            flex-shrink: 0;
            display: flex;
            flex-direction: row;
            align-items: center;
            padding: 0 24rpx;
            height: 100%;
        }
    }
    .list-wrap {
        width: 100%;
        transition: height 1s;
        .list {
            width: 100%;
            max-height: 600rpx;
            .item {
                display: flex;
                flex-direction: row;
                align-items: center;
                justify-content: space-between;
                height: 80rpx;
                margin: 0 30rpx;
                border-top: 1rpx solid var(--c-border);
            }
        }
    }
}
</style>
